view this document with Notepad 800*600


                     L                ZZZZZZ         RRRRR           SSSSS
                     L                    Z          R    R         S
                     L          aaa      Z      aaa  R    R  u   u  S
                     L            a     Z         a  RRRRR   u   u  SSSSS
               XX    L         aaaa    Z       aaaa  R    R  u   u       S
              XXXX   L        a   a   Z       a   a  R    R  u   u       S
             XXXXXX  LLLLLLL  aaaaa  ZZZZZZZ  aaaaa  R    R  uuuuu  SSSSSS
             XXXXXX       
        XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
       XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
        XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
             XXXXXX
             XXXXXX
              XXXX        proudly presents his 4.Cracking Tutorial (29.03.1999)
               XX


This time I show you how to locate strings in C++ Builder programs that are not hardcoded.
It is pretty easy. I found it when I coded the Hellforge General CrackMe II. So don't read on
if you haven't cracked it, yet. This will steal your fun (and mine when I'm thinking how much
reversers will sit in front of their PC and don't have an idea how to start.)
A little example:


* Referenced by a CALL at Address:
|:00403ACA   
|
:0040161C 55                      push ebp
:0040161D 8BEC                    mov ebp, esp
:0040161F 81C43CFFFFFF            add esp, FFFFFF3C
:00401625 B87C544000              mov eax, 0040547C
:0040162A E82D270000              call 00403D5C
:0040162F 66C7854CFFFFFF0800      mov word ptr [ebp+FFFFFF4C], 0008
:00401638 8D45F4                  lea eax, dword ptr [ebp-0C]
* Reference To: Project1.System::AnsiString::AnsiString(void())
                                  |
:0040163B E808070000              call 00401D48
:00401640 50                      push eax
:00401641 FF8558FFFFFF            inc dword ptr [ebp+FFFFFF58]

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040160B(C)
|
:00401647 8D45F8                  lea eax, dword ptr [ebp-08]
:0040164A B252                    mov dl, 52
:0040164C E8DB280000              call 00403F2C
:00401651 50                      push eax
:00401652 FF8558FFFFFF            inc dword ptr [ebp+FFFFFF58]
:00401658 8D45FC                  lea eax, dword ptr [ebp-04]
:0040165B B257                    mov dl, 57
:0040165D E8CA280000              call 00403F2C
:00401662 FF8558FFFFFF            inc dword ptr [ebp+FFFFFF58]
:00401668 5A                      pop edx
:00401669 59                      pop ecx
:0040166A E8BD290000              call 0040402C
:0040166F 8D45F4                  lea eax, dword ptr [ebp-0C]
:00401672 50                      push eax

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00401608(C)
|
:00401673 8D45EC                  lea eax, dword ptr [ebp-14]
* Reference To: Project1.System::AnsiString::AnsiString(void())
                                  |
:00401676 E8CD060000              call 00401D48
:0040167B 50                      push eax
:0040167C FF8558FFFFFF            inc dword ptr [ebp+FFFFFF58]
:00401682 8D45F0                  lea eax, dword ptr [ebp-10]
:00401685 B24F                    mov dl, 4F
:00401687 E8A0280000              call 00403F2C
:0040168C 8BD0                    mov edx, eax
:0040168E FF8558FFFFFF            inc dword ptr [ebp+FFFFFF58]
:00401694 59                      pop ecx
:00401695 58                      pop eax
:00401696 E891290000              call 0040402C
:0040169B 8D45EC                  lea eax, dword ptr [ebp-14]
:0040169E 50                      push eax
:0040169F 8D45E4                  lea eax, dword ptr [ebp-1C]
* Reference To: Project1.System::AnsiString::AnsiString(void())
                                  |
:004016A2 E8A1060000              call 00401D48
:004016A7 50                      push eax
:004016A8 FF8558FFFFFF            inc dword ptr [ebp+FFFFFF58]
:004016AE 8D45E8                  lea eax, dword ptr [ebp-18]
:004016B1 B24E                    mov dl, 4E
:004016B3 E874280000              call 00403F2C
:004016B8 8BD0                    mov edx, eax
:004016BA FF8558FFFFFF            inc dword ptr [ebp+FFFFFF58]
:004016C0 59                      pop ecx
:004016C1 58                      pop eax
:004016C2 E865290000              call 0040402C
:004016C7 8D45E4                  lea eax, dword ptr [ebp-1C]
:004016CA 50                      push eax
:004016CB 8D45DC                  lea eax, dword ptr [ebp-24]
* Reference To: Project1.System::AnsiString::AnsiString(void())
                                  |
:004016CE E875060000              call 00401D48
:004016D3 50                      push eax
:004016D4 FF8558FFFFFF            inc dword ptr [ebp+FFFFFF58]
:004016DA 8D45E0                  lea eax, dword ptr [ebp-20]
:004016DD B247                    mov dl, 47
:004016DF E848280000              call 00403F2C
:004016E4 8BD0                    mov edx, eax
:004016E6 FF8558FFFFFF            inc dword ptr [ebp+FFFFFF58]
:004016EC 59                      pop ecx
:004016ED 58                      pop eax
:004016EE E839290000              call 0040402C
:004016F3 8D45DC                  lea eax, dword ptr [ebp-24]
:004016F6 50                      push eax
:004016F7 8D45D4                  lea eax, dword ptr [ebp-2C]
...

Think you didn't get much from this code snippet, so I'll explain:

I coded the word WRONG in C++ in this way
String wrong=String(char(87))+String(char(82))+String(char(79))+String(char(78))+String(char(71))

When you look some lines below * Reference To: Project1.System::AnsiString::AnsiString(void()) 
you see something like mov dl, XX (00<=XX<=FF).

Let's take these lines:
:0040164A B252                    mov dl, 52
:0040165B B257                    mov dl, 57
:00401685 B24F                    mov dl, 4F
:004016B1 B24E                    mov dl, 4E
:004016DD B247                    mov dl, 47

Guess what. These are the hex-values for decimal and ASCII:
52 = 87 = W
57 = 82 = R
4F = 79 = O
4E = 78 = N
47 = 71 = G

Where are they saved so that we can locate them during the program ?
The address where the char is to be saved is calculated in the first CALL after the mov dl, XX.
Look at the EBP register. If a new value is copied near it this is a pointer to the address
where the char is stored. (It seems to be EBP-08, but I am no ASM god so look at
changes near EBP) Now the address is increased and the new value is assigned to EBP and
the next char is copied to the next address.

This is strange: C++ Builder copies the Bytes to the RAM like this:
First char (W) is stored. Then second char (R) is stored above and below they are added.
Then the third char (O) is stored below the WR and WR is added with O 16 bytes later and
so on.

[00972170] - 00000052  R...       
[00972174] - 00000012  ....       ;; ??? (can anybody tell me what this line means?)
[00972178] - 00000001  ....       ;; ??? (can anybody tell me what this line means?)
[0097217C] - 00000001  ....       
[00972180] - 00000057  W...       
[00972184] - 00000012  ....
[00972188] - 00000001  ....
[0097218C] - 00000002  ....
[00972190] - 00005257  WR..
[00972194] - 00000012  ....
[00972198] - 00000001  ....
[0097219C] - 00000001  ....
[009721A0] - 0000004f  O...
[009721A4] - 00000012  ....
[009721A8] - 00000001  ....
[009721AC] - 00000003  ....
[009721B0] - 004f5257  WRO.
[009721B4] - 00000012  ....
[009721B8] - 00000001  ....
[009721BC] - 00000001  ....
[009721C0] - 0000004e  N...
[009721C4] - 00000016  ....
[009721C8] - 00000001  ....
[009721CC] - 00000004  ....
[009721D0] - 4e4f5257  WRON
[009721D8] - 00000012  ....
[009721DC] - 00000001  ....
[009721E0] - 00000001  ....
[009721E4] - 00000047  G...
[009721E8] - 00000016  ....
[009721EC] - 00000001  ....
[009721F0] - 00000005  ....
[009721F4] - 4e4f5257  WRON
[009721F8] - 00000047  G...
[009721D8] - 00000012  ....
[009721DC] - 00000001  ....
[009721E0] - 00000001  ....

Isn't it possible, that they store it like this immediately:
Put first char to 00972170, increase pointer by 1 byte and copy the next char to 00972171 and so
on.

[00972170] - 4e4f5257  WRON
[009721F4] - 00000047  G...

In this way you only need 5 bytes of RAM to store WRONG. In Borland's way they need 40 bytes.

Little Explaination:
You surely recognized that the hex-values don't fit to the ASCII values. You have to turn the
hex-values: 4e4f5257 will be 57524f4e. This is, because the RAM is counted downwards or something
like that. For an exact answer ask in a forum at http://www.proweb.co.uk/~greenway.

BTW
Hope my tutorial was helpful for you and see you again in my next tutorial. 
If not see visit our webpage.
     
Greets to: tKC, Ed!son, Moral Insanity, The Sandman, Eternal Bliss, DaVinci and all [hf] members

VI.  All Tutorials by LaZaRuS [hf]
      
#|  date  |   name           |version|W32Dasm|Soft-Ice|kind of crack            |
-|--------|------------------|-------|-------|--------|-------------------------|
1|20.01.99|Jaylock           |1,0,0,1|  (X)  |   (X)  |serial#                  |
2|31.01.99|Goldwave          |4.02   |  (X)  |   (X)  |serial#,nag-screens      |
3|28.03.99|AxMan             |3.00   |  (X)  |   (X)  |serial#,remove date-limit|
4|29.03.99|C++Builder Strings|       |  (X)  |   (X)  |how to find strings in   |
 |        |                  |       |       |        |C++ Builder that are not |
 |        |                  |       |       |        |hardcoded
     
LaZaRuS [hf]
Visit Hellforge at http://members.xoom.com/hell_crack for more tutorials and high quality
cracking links.
If you want to mail me: lazarus666@gnwmail.com